<script setup lang="ts">
defineOptions({name: 'OperateLog'})
import { ElMessageBox } from 'element-plus'
import {useTable} from '@/composables/useTable'
import {formatEnumData, dateFormat} from '@/utils/helper'
import {useI18n} from 'vue-i18n'
import {getOperateLogList, deleteOperateLog, batchDeleteOperateLog} from '@/api/operate-log'
import {getEnumData} from '@/api/enum'
import {getLanguageData} from '@/api/language'
import Search from './modules/search.vue'
import Detail from './modules/detail.vue'

/**
 * 变量部分
 */
const {t} = useI18n()
const enumData = ref<any>({})
const enumDataFormat = ref<any>({})
const languageData = ref<any>({})
const sortField = new Map<string, any>()
const tableRef = ref()
const detailRef = ref()
const selectedData = ref<any>([])

onMounted(async () => {
	await getLanguage()
	await getEnum()
})

/**
 * 表格函数
 */
const {
	columns,
	columnChecks,
	data,
	loading,
	pagination,
	updateColumn,
	searchParams,
	handleSizeChange,
	handleCurrentChange,
	resetSearchParams,
	refreshData,
	getDataDebounced,
} = useTable({
	// 核心配置
	core: {
		apiFn: getOperateLogList,
		apiParams: {
			page: 1,
			limit: 10,
		},
		columnsFactory: () => [
			{type: 'selection', width: 50},
			{prop: 'operate', label: t('common.operate'), width: 110, useSlot: true},
			{prop: 'operateId', minWidth: 100},
			{prop: 'path', minWidth: 130},
			{prop: 'method', width: 138},
			{prop: 'params', minWidth: 180},
			{prop: 'operateBefore', minWidth: 180},
			{prop: 'operateAfter', minWidth: 180},
			{prop: 'ip', width: 140},
			{
				prop: 'createTime', label: t('common.field.createTime'), width: 170, useSlot: true,
				sortable: 'custom',
			}
		]
	},
	hooks: {
		onSuccess: (data) => {
			handleSelectFeedback(data)
		}
	}
})

/**
 * 获取枚举数据
 */
const getEnum = async () => {
	enumData.value = await getEnumData({modules: ['operateLog']})
	enumDataFormat.value = formatEnumData(enumData.value)
}

/**
 * 获取语言数据
 */
const getLanguage = async () => {
	const res: any = await getLanguageData({modules: ['operateLog']});
	languageData.value = {...res};
	for (let key in res.operateLog.field) updateColumn?.(key, {label: res.operateLog.field[key]})
}

/**
 * 处理排序改变
 * @param params
 */
const handleSortChange = (params: any) => {
	const hasProp = sortField.has(params.prop);
	if (hasProp && params.order === null) sortField.delete(params.prop)
	else sortField.set(params.prop, params.order)
	let orderBy: any = {};
	for (const [key, value] of sortField) if (value) orderBy[key] = value === 'ascending' ? 'asc' : 'desc'
	Object.assign(searchParams, {orders: {...orderBy}})
	getDataDebounced()
}

/**
 * 处理表头单元格的 className 的回调方法
 * @param column
 */
const handleHeaderCellClassName = ({column}: { column: any }) => {
	if (sortField.has(column.property)) column.order = sortField.get(column.property)
	return ''
}

/**
 * 处理搜索重置
 * @param filterData
 */
const handleSearchReset = (filterData: any) => {
	resetSearchParams()
	Object.assign(searchParams, {...filterData})
	getDataDebounced()
}

/**
 * 处理搜索确认
 * @param filterData
 */
const handleSearchConfirm = (filterData: any) => {
	resetSearchParams()
	Object.assign(searchParams, {...filterData})
	getDataDebounced()
}

/**
 * 处理选择
 * @param selection
 * @param row
 */
const handleSelect = (selection: any, row: any) => {
	const selectedIds = selectedData.value.map((item: any) => item.id)
	const index = selectedIds.indexOf(row.id)
	if (index === -1) selectedData.value.push(row)
	else selectedData.value.splice(index, 1)
}

/**
 * 处理全选
 * @param selection
 */
const handleSelectAll = (selection: any) => {
	const selectionLength = selection.length
	const selectedIds = selectedData.value.map((item: any) => item.id)
	if (selectionLength === 0) {
		data.value.forEach((item: any) => {
			const index = selectedIds.indexOf(item.id);
			if (index !== -1) selectedIds.splice(index, 1)
		})
		const newSelection: any = [];
		selectedData.value.forEach((item: any) => {
			if (selectedIds.indexOf(item.id) !== -1) newSelection.push(item)
		})
		selectedData.value = newSelection
	} else {
		data.value.forEach((item: any) => {
			if (selectedIds.indexOf(item.id) === -1) selectedData.value.push(item)
		})
	}
}

/**
 * 处理选择回显
 * @param thisData
 */
const handleSelectFeedback = (thisData: any) => {
	nextTick(() => {
		if (selectedData.value.length > 0 && tableRef.value) {
			const thisIds = thisData.map((item: any) => item.id)
			selectedData.value.forEach((item: any) => {
				if (thisIds.indexOf(item.id) !== -1) {
					tableRef.value.elTableRef.toggleRowSelection(item, true)
				}
			});
		}
	})
}

/**
 * 处理删除
 * @param id
 */
const handleDelete = async (id: number) => {
	ElMessageBox.confirm(t('common.deleteTip'), t('common.deleteConfirm'), {
		confirmButtonText: t('common.confirm'), cancelButtonText: t('common.cancel'),
		type: 'error', draggable: true
	}).then(() => {
		loading.value = true
		deleteOperateLog({id: id}).then(() => refreshData()).finally(() => loading.value = false)
	}).catch(() => {})
}

/**
 * 处理批量删除
 */
const handleBatchDelete = async () => {
	const ids = selectedData.value.map((item: any) => item.id)
	ElMessageBox.confirm(t('common.batchDeleteTip'), t('common.deleteConfirm'), {
		confirmButtonText: t('common.confirm'), cancelButtonText: t('common.cancel'),
		type: 'error', draggable: true
	}).then(() => {
		loading.value = true
		batchDeleteOperateLog({ids: ids}).then(() => {
			selectedData.value = []
			refreshData()
		}).finally(() => loading.value = false)
	}).catch(() => {})
}

const handleDetail = (id: number) => detailRef.value.open(id)
</script>

<!-- art-full-height 自动计算出页面剩余高度 -->
<!-- art-table-card 一个符合系统样式的 class，同时自动撑满剩余高度 -->
<!-- 更多 useTable 使用示例请移步至 功能示例 下面的 高级表格示例 -->
<template>
	<div class="art-full-height">
		<!-- 搜索栏 -->
		<Search :enumData="enumData" :languageData="languageData" @reset="handleSearchReset"
			@search="handleSearchConfirm"/>

		<ElCard class="art-table-card" shadow="never">
			<!-- 表格头部 -->
			<ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData">
				<template #left>
					<ElSpace wrap>
						<ElButton v-auth="'operateLogBatchDelete'"
							  :disabled="selectedData.length === 0"
							  @click="handleBatchDelete"
							  v-ripple>
							{{ t('common.batchDelete') }}({{ selectedData.length }})
						</ElButton>
					</ElSpace>
				</template>
			</ArtTableHeader>

			<!-- 表格 -->
			<ArtTable
				ref="tableRef"
				rowKey="id"
				:loading="loading"
				:data="data"
				:columns="columns"
				:show-overflow-tooltip="true"
				:select-on-indeterminate="true"
				:header-cell-class-name="handleHeaderCellClassName"
				:pagination="pagination"
				@pagination:size-change="handleSizeChange"
				@pagination:current-change="handleCurrentChange"
				@sort-change="handleSortChange"
				@select="handleSelect"
				@select-all="handleSelectAll"
			>
				<template #operate="{row}">
					<ArtButtonTable type="view" @click="handleDetail(row.id)"/>
					<ArtButtonTable type="delete" @click="handleDelete(row.id)"/>
				</template>
				<template #createTime="{row}">{{ dateFormat(row.createTime) }}</template>
			</ArtTable>
		</ElCard>
		<Detail ref="detailRef" :enumData="enumData" :languageData="languageData"/>
	</div>
</template>

<style lang="scss" scoped>

</style>
